//****************************************************
// Porman Project 2
// Filename: CVertexDeclObject.cpp
// Date: 2009/03/21
// Author: KengYu Lin
// Modify:
//****************************************************
#include "CVertexDeclObject.h"

namespace Porman
{

namespace GL
{

//------------------------------
// class CVertexElementArray
//------------------------------
CVertexElementArray::CVertexElementArray( void )
{
}

CVertexElementArray::CVertexElementArray( const CVertexElementArray& l )
{
    (*this) = l;
}

CVertexElementArray& CVertexElementArray::operator=( const CVertexElementArray& l )
{
    m_vectVEArray = l.m_vectVEArray;
    return (*this);
}

void CVertexElementArray::setVE( const char* pSemantic, int iSemanticIndex, EVertexEleType enumType, int iOffset, int iUsageIndex )
{
    SVertexElement VE( pSemantic, iSemanticIndex, enumType, iOffset, iUsageIndex );
    m_vectVEArray.push_back( VE );
}

void CVertexElementArray::setVE( SVertexElement& VE )
{
    m_vectVEArray.push_back( VE );
}

SVertexElement CVertexElementArray::getVE( int iIndex )
{
    if( getNumOfVE() != 0 && iIndex >= 0 && iIndex < getNumOfVE() )
        return m_vectVEArray[iIndex];
    else
        return SVertexElement();
}

int CVertexElementArray::getNumOfVE( void )
{
    return static_cast<int>( m_vectVEArray.size() );
}

//------------------------------
// class CVertexDeclObject
//------------------------------
CVertexDeclObject::CVertexDeclObject( CRenderDevice* pDevice ) :
CBaseObject(pDevice),
m_vectSData(),
m_VertexElements()
{
    setName("Non");
    m_iNumOfVertexDeclObj++;
}

CVertexDeclObject::~CVertexDeclObject( void )
{
    m_iNumOfVertexDeclObj--;
}

bool CVertexDeclObject::_processDataArray( SVertexElement* pVertexElementsArray )
{
    int iNumOfElements = 0;
    SVertexElement* pVElement = pVertexElementsArray;
    while( pVElement->m_iOffset != -1 )
    {
        _processData( (*pVElement) );
        m_VertexElements.setVE( (*pVElement) );
        iNumOfElements++;
        pVElement++;
    }

    return (iNumOfElements != 0 ? true : false);
}

bool CVertexDeclObject::_processDataArray( CVertexElementArray* pVertexElementsArray )
{
    int iCount= static_cast<int>( pVertexElementsArray->m_vectVEArray.size() );
    if( iCount != 0 )
    {
        for( int i=0; i<iCount; i++ )
            _processData( pVertexElementsArray->m_vectVEArray[i] );

        m_VertexElements = (*pVertexElementsArray);
        return true;
    }
    else
        return false;
}

void CVertexDeclObject::_processData( SVertexElement& VElement )
{
    SData data;
    data.m_sSemantic = VElement.m_sSemantic;
    data.m_iOffset = VElement.m_iOffset;
    data.m_iUsageIndex = VElement.m_iUsageIndex;
    _calculateSizeAndType( VElement, data.m_iStride, data.m_iType );

    m_vectSData.push_back( data );
}

inline void CVertexDeclObject::_calculateSizeAndType( SVertexElement& VElements, int& iStride, int& iType )
{
    if( VElements.m_iType >= E_VERTEXELETYPE_FLOAT && VElements.m_iType <= E_VERTEXELETYPE_FLOAT4 )
    {
        iType = GL_FLOAT;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_BYTE && VElements.m_iType <= E_VERTEXELETYPE_BYTE4 )
    {
        iType = GL_BYTE;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_UNSIGNED_BYTE && VElements.m_iType <= E_VERTEXELETYPE_UNSIGNED_BYTE4 )
    {
        iType = GL_UNSIGNED_BYTE;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_SHORT && VElements.m_iType <= E_VERTEXELETYPE_SHORT4 )
    {
        iType = GL_SHORT;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_UNSIGNED_SHORT && VElements.m_iType <= E_VERTEXELETYPE_UNSIGNED_SHORT4 )
    {
        iType = GL_UNSIGNED_SHORT;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_INT && VElements.m_iType <= E_VERTEXELETYPE_INT4 )
    {
        iType = GL_INT;
    }
    else if( VElements.m_iType >= E_VERTEXELETYPE_UNSIGNED_INT && VElements.m_iType <= E_VERTEXELETYPE_UNSIGNED_INT4 )
    {
        iType = GL_UNSIGNED_INT;
    }

    iStride = (VElements.m_iType % 4) + 1;
}

}//End namespace GL

}//End namespace Porman